package com.we.wecc.aw.mid.impl;

import com.alibaba.fastjson.JSONObject;
import com.we.wecc.aw.db.mapper.*;
import com.we.wecc.aw.db.model.*;
import com.we.wecc.aw.mid.model.out.AwardOut;
import com.we.wecc.aw.mid.model.out.TemperatureIn;
import com.we.wecc.aw.mid.service.AwardService;
import com.we.wecc.us.db.mapper.UserMapper;
import com.we.wecc.us.db.model.User;
import com.x.share.db.model.Pagination;
import com.x.share.mid.exception.HelperException;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.we.wecc.aw.db.AwardEnum.AwardStatus.*;
import static com.x.share.mid.utils.PrizeUtils.getPrizeIndex;


@Service
public class AwardServiceImpl implements AwardService {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    AwardMapper awardMapper;

    @Resource
    AwardInvestLogMapper awardInvestLogMapper;

    @Resource
    FriendsBoostMapper friendsBoostMapper;

    @Resource
    AwardProductMapper awardProductMapper;

    @Resource
    AwardWinMapper awardWinMapper;

    @Resource
    UserMapper userMapper;

    @Override
    public Pagination<AwardOut> getAwardList(Integer awardStatus, Integer pageNo, Integer pageSize) {
        RowBounds rb = new RowBounds(Pagination.offset(pageNo, pageSize), Pagination.limit(pageSize));
        AwardExample ex = new AwardExample();
        ex.setOrderByClause("createTime desc");
        ex.or().andDelFlagEqualTo(0).andAwardStatusEqualTo(awardStatus);
        List<Award> list = awardMapper.selectByExampleWithBLOBsWithRowbounds(ex, rb);
        int count = (int) awardMapper.countByExample(ex);
        List<AwardOut> outItem = new ArrayList<>();
        list.forEach(s -> {//不带热度，热度在更改完成状态时update
            AwardOut out = AwardOut.from(s);
            AwardProduct ap = awardProductMapper.selectByPrimaryKey(out.getProductId());
            out.setAwardProductInfo(AwardOut.AwardProductInfo.from(ap));
            if (awardStatus == EXCHANGED.getCode() || awardStatus == COMPLETED.getCode()) {
                AwardWinExample winExample = new AwardWinExample();
                winExample.or().andAwardIdEqualTo(s.getId());
                List<AwardWin> winList = awardWinMapper.selectByExample(winExample);
                if (winList.isEmpty()) {
                    throw new HelperException("开奖系统出错了！请联系管理员！");
                }
                User user = userMapper.selectByPrimaryKey(winList.get(0).getUserId());
                JSONObject json = new JSONObject();
                json.put("userName", user.getName());
                json.put("userId", user.getId());
                json.put("img",user.getHeadimage());
                json.put("djStatus", winList.get(0).getCashPrizeState());
                out.setData(json.toJSONString());
            }
            outItem.add(out);

        });
        return new Pagination<>(outItem, count, pageNo, pageSize);
    }

    @Override
    public AwardOut getAward(int awardId) {
        Award a = awardMapper.selectByPrimaryKey(awardId);
        AwardProduct ap = awardProductMapper.selectByPrimaryKey(a.getProductId());
        AwardOut out = AwardOut.from(a);
        out.setAwardProductInfo(AwardOut.AwardProductInfo.from(ap));
        return out;
    }

    /**
     * 100根据时间前台算  200直接显示 400是往期
     *
     * @return
     */
    @Override
    public AwardOut getCurrentAward() {
        AwardExample ex = new AwardExample();
        List<Integer> status = Arrays.asList(100, 200);
        ex.or().andDelFlagEqualTo(0).andAwardStatusIn(status);
        List<Award> list = awardMapper.selectByExample(ex);
        if (list.isEmpty()) {
            throw new HelperException("当前活动出错!");
        }
        AwardOut out = AwardOut.from(list.get(0));
        planTemperature(out.getId()).from(out);
        AwardProduct ap = awardProductMapper.selectByPrimaryKey(out.getProductId());
        out.setAwardProductInfo(AwardOut.AwardProductInfo.from(ap));
        return out;
    }

    /**
     * 实时计算热度
     */
    public TemperatureIn planTemperature(int awardId) {
        TemperatureIn in = new TemperatureIn();

        Award award = awardMapper.selectByPrimaryKey(awardId);

        FriendsBoostExample ex = new FriendsBoostExample();
        ex.or().andAwardIdEqualTo(awardId);
        int boostSum = (int) friendsBoostMapper.countByExample(ex);

        AwardInvestLogExample logEx = new AwardInvestLogExample();
        logEx.or().andAwardIdEqualTo(awardId);
        List<AwardInvestLog> awardInvestLogs = awardInvestLogMapper.selectByExample(logEx);

        int partnerNum = (int) awardInvestLogs.stream()
                .map(s -> s.getUserId())
                .distinct()
                .count();

        int partnerTimes = (int) awardInvestLogMapper.countByExample(logEx);

        Double weccNum = awardInvestLogs.stream()
                .map(s -> s.getNum())
                .reduce(Double::sum)
                .get();

        in.setBoostSum(boostSum);
        in.setPartnerNum(partnerNum);
        in.setPartnerTimes(partnerTimes);
        in.setWeccNum(weccNum);
        in.setTemperature(weccNum / award.getAmount());
        return in;
    }

    @Override
    public void x(int awardId) {
        TemperatureIn in = planTemperature(awardId);
        Award a = awardMapper.selectByPrimaryKey(awardId);
        AwardInvestLogExample ex = new AwardInvestLogExample();
        ex.or().andAwardIdEqualTo(awardId);
        List<AwardInvestLog> list = awardInvestLogMapper.selectByExample(ex);
        if (list.isEmpty()) {
            throw new HelperException("输入的活动id出错！");
        }
        if (in.getTemperature() < 1) {
            if (System.currentTimeMillis() - a.getEndTime().getTime() >= 0) {
                a.setAwardStatus(UNDONE.getCode());
                a.setBoostNum(in.getBoostSum());
                a.setPartnerNum(in.getPartnerNum());
                a.setWeccNum(in.getWeccNum());
                a.setTemperature(in.getTemperature());
                awardMapper.updateByPrimaryKeySelective(a);
                logger.info("未达标结束---------------------------------");
                return;
            }
            return;
        }
        //好友部分
        Map<Long, Long> collect = list.stream().collect(Collectors.groupingBy(AwardInvestLog::getUserId, Collectors.counting()));
        Map<Long, Long> ret = new HashMap<>();
        for (Long s : collect.keySet()) {
            FriendsBoostExample fEx = new FriendsBoostExample();
            fEx.or().andUserIdEqualTo(s);
            int i = (int) friendsBoostMapper.countByExample(fEx);
            int q = i < a.getBoostLim() ? i : a.getBoostLim();
            ret.put(s, (Long) (collect.get(s) + q));
        }
        int selected = getPrizeIndex(ret);
        Long userId = collect.get(selected);
        logger.info("中奖用户为 ----------------------- >%s", userId);
        AwardWinExample win = new AwardWinExample();
        win.or().andAwardIdEqualTo(awardId);
        List<AwardWin> w = awardWinMapper.selectByExample(win);
        if (w.isEmpty()) {
            AwardWin aw = new AwardWin();
            aw.setAwardId(awardId);
            aw.setUserId(userId);
            aw.setCreateTime(new Date());
            awardWinMapper.insertSelective(aw);
        }
        //修改活动状态
        a.setBoostSum(in.getBoostSum());
        a.setPartnerNum(in.getPartnerNum());
        a.setWeccNum(in.getWeccNum());
        a.setTemperature(in.getTemperature());
        a.setAwardStatus(EXCHANGED.getCode());
        awardMapper.updateByPrimaryKeySelective(a);
        logger.info("达标结束 -----------------------");
    }

    @Override
    public void ready() {
        AwardExample ex = new AwardExample();
        ex.or().andStartTimeEqualTo(new Date());
        List<Award> list = awardMapper.selectByExample(ex);
        if (list.isEmpty()) {
            throw new HelperException("活动设置有误！");
        }
        list.get(0).setAwardStatus(READY.getCode());
        awardMapper.updateByPrimaryKeySelective(list.get(0));
        logger.info("预热开始 -----------------------");
    }
}